package cloud.tianai.mate.captcha.interceptor.group;

import cloud.tianai.captcha.common.AnyMap;
import cloud.tianai.captcha.common.response.ApiResponse;
import cloud.tianai.captcha.common.util.CollectionUtils;
import cloud.tianai.captcha.generator.common.model.dto.GenerateParam;
import cloud.tianai.captcha.interceptor.CaptchaInterceptorGroup;
import cloud.tianai.captcha.interceptor.Context;
import cloud.tianai.captcha.validator.common.model.dto.ImageCaptchaTrack;
import cloud.tianai.captcha.application.vo.CaptchaResponse;
import cloud.tianai.captcha.application.vo.ImageCaptchaVO;
import cloud.tianai.captcha.cache.CacheStore;

import java.util.concurrent.TimeUnit;
import java.util.function.Function;

public class FeaturesCaptchaInterceptorGroup extends CaptchaInterceptorGroup {

    public static final String NAME = "feature_group_interceptor";

    private final CacheStore cacheStore;
    private final Function<Context, String> getKeyFunc;
    private final Long expire = 120 * 60 * 1000L;
    public static final String DATA_FEATURES_KEY = "features_key";
    public static final String DATA_FEATURES = "features";


    public FeaturesCaptchaInterceptorGroup(CacheStore cacheStore, Function<Context, String> getKeyFunc) {
        this.cacheStore = cacheStore;
        this.getKeyFunc = getKeyFunc;
        setName(NAME);
    }

    @Override
    public CaptchaResponse<ImageCaptchaVO> beforeGenerateCaptcha(Context context, String type, GenerateParam param) {
        context = createContextIfNecessary(context);
        String key = getKeyFunc.apply(context);
        AnyMap features = getFeatures(key);
        context.putData(DATA_FEATURES_KEY, key);
        context.putData(DATA_FEATURES, features);
        return super.beforeGenerateCaptcha(context, type, param);
    }


    @Override
    public ApiResponse<?> beforeValid(Context context, String type, ImageCaptchaTrack imageCaptchaTrack, AnyMap validData) {
        context = createContextIfNecessary(context);
        if (context.isStart()) {
            String key = getKeyFunc.apply(context);
            AnyMap features = getFeatures(key);
            context.putData(DATA_FEATURES_KEY, key);
            context.putData(DATA_FEATURES, features);
        }
        ApiResponse<?> response = super.beforeValid(context, type, imageCaptchaTrack, validData);

        if (context.isEnd()) {
            String key = context.getData(DATA_FEATURES_KEY, String.class);
            AnyMap features = context.getData(DATA_FEATURES, AnyMap.class);
            cacheFeatures(key, features);
        }
        if (!response.isSuccess()) {
            // 全部停止,验证失败
            context.end();
        }
        return response;
    }

    @Override
    public ApiResponse<?> afterValid(Context context, String type, ImageCaptchaTrack imageCaptchaTrack, AnyMap validData, ApiResponse<?> basicValid) {
        context = createContextIfNecessary(context);
        if (context.isStart()) {
            String key = getKeyFunc.apply(context);
            AnyMap features = getFeatures(key);
            context.putData(DATA_FEATURES_KEY, key);
            context.putData(DATA_FEATURES, features);
        }
        ApiResponse<?> response = super.afterValid(context, type, imageCaptchaTrack, validData, basicValid);
        if (context.isEnd()) {
            String key = context.getData(DATA_FEATURES_KEY, String.class);
            AnyMap features = context.getData(DATA_FEATURES, AnyMap.class);
            cacheFeatures(key, features);
        }
        if (!response.isSuccess()) {
            // 全部停止,验证失败
            context.end();
        }
        return response;
    }

    private AnyMap getFeatures(String key) {
        AnyMap cache = cacheStore.getCache(key);
        if (cache == null) {
            cache = new AnyMap();
        }
        return cache;
    }

    private void cacheFeatures(String key, AnyMap features) {
        if (!CollectionUtils.isEmpty(features)) {
            cacheStore.setCache(key, features, expire, TimeUnit.MILLISECONDS);
        }
    }
}
